using System;
using SudokuHelper.Model.Values;

namespace SudokuHelper.Model {
    public class SudokuDesk : ICloneable, ISudokuDesk {
        #region Private members

        private readonly IValue[,] cells = new IValue[9,9];

        #endregion

        #region Events

        public event EventHandler<CellValueChangedEventArgs> CellValueChanged;

        #endregion

        #region Properties

        public virtual IValue this[int row, int col] {
            get {
                return cells[row, col];
            }

            set {
                if (!CheckItemValid(row, col, value))
                    throw new SudokuValueException();

                if(cells[row,col]!=value){
                    cells[row, col] = value;
                    RaiseCellValueChanged(row, col);
                }
            }
        }

        /// <summary>
        /// Provides direct access to cells 
        /// </summary>
        protected IValue[,] Cells {
            get { return cells; }
        }

        #endregion

        #region Utility methods

        public bool CheckItemValid(int row, int col, IValue value) {
            return new DeskValidator(this, row, col).Validate(value);
        }

        protected void RaiseCellValueChanged(int row,int col) {
            var handler = CellValueChanged;
            if (handler != null)
                handler(this, new CellValueChangedEventArgs(row, col, cells[row, col]));
        }

        #endregion

        #region Implementation of ICloneable

        public object Clone() {
            var desk = new SudokuDesk();
            for (int i = 0; i < cells.GetUpperBound(0); i++){
                for (int j = 0; j < cells.GetUpperBound(1); j++){
                    desk.cells[i, j] = cells[i, j];
                }
            }

            return desk;
        }

        #endregion
    }
}